<template>
  <div ref="tooltipData" v-loading="isLoading" class="tooltip-data">
    <PanelLabelOverflowTooltip ref="panelLabelOverflowTooltip" />
    <el-form
      ref="form"
      v-panel-label-overflow-tooltip="getPanelLabelOverflowTooltip()"
      :model="form"
      label-width="100px"
      :rules="rules"
    >
      <VsFormItem v-if="isChildComponent" :label="$demoi18n('common.usingParentData')" prop="useParentData">
        <el-switch v-model="form.useParentData"></el-switch>
      </VsFormItem>

      <div v-if="!form.useParentData || !isChildComponent">
        <!-- 数据源类型 -->
        <VsFormItem :label="$demoi18n('panel.label.dataSourceType')" prop="dataSourceType">
          <el-select
            v-model="form.dataSourceType"
            size="default"
            :class="'panel-data-select-' + xvueTheme"
            :popper-class="'select-poper-' + xvueTheme"
            @change="onDatasourceTypeChange"
          >
            <el-option
              v-for="item in dataSourceTypeOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            ></el-option>
          </el-select>
        </VsFormItem>

        <!-- 数据源 -->
        <VsFormItem
          v-if="form.dataSourceType !== 'xVueApi'"
          :label="$demoi18n('panel.label.selectDataSource')"
          prop="dataSource"
        >
          <el-select
            v-model="form.dataSource"
            size="default"
            filterable
            :class="'panel-data-select-' + xvueTheme"
            :popper-class="'select-poper-' + xvueTheme"
            @change="onDatasourceChange"
          >
            <el-option
              v-for="item in dataSourceList"
              :key="item.id"
              :label="item.option_label"
              :value="item.option_value"
            ></el-option>
          </el-select>
        </VsFormItem>

        <!-- 3.选择Api (xMiner) -->
        <VsFormItem v-if="isXMiner" :label="$demoi18n('panel.label.selectApi')" prop="apiCode">
          <XMinerApiList
            v-model:value="form.apiCode"
            :api-list="apiList"
            @change="onApiCodeChange"
          />
        </VsFormItem>

        <!-- 3.选择API (fabric) -->
        <VsFormItem v-if="form.dataSourceType === 'fabric'" :label="$demoi18n('panel.label.selectApi')" prop="apiCode">
          <FabricApiList
            v-model:value="form.apiCode"
            :api-list="apiList"
            @change="onApiCodeChange"
          />
        </VsFormItem>

        <!-- xVue页面api数据源设置 -->
        <div v-if="form.dataSourceType === 'xVueApi'" class="xVueApiData">
          <VsFormItem :form="form" path="dataVal" :confs="fItemConf" placeholder="{{api1.data}}" />
        </div>

        <!-- 自动刷新设置 -->
        <AutoRefreshSetting v-if="form.dataSourceType !== 'xVueApi'" :form="form" :config="{}" :useFor="useFor" />
        <VsFormItem v-show="useFor === 'tooltip' && showCorrelation" prop="correlation" label-width="50px">
          <el-radio-group v-model="form.correlation" size="default">
            <el-radio label="correlate">{{ $demoi18n('panel.tootipData.dataCorrelate') }}</el-radio>
            <el-radio label="discorrelate">{{ $demoi18n('panel.tootipData.dataDiscorrelate') }}</el-radio>
          </el-radio-group>
        </VsFormItem>

        <!-- 选中数据关联展示 -->
        <div v-if="form.correlation === 'correlate' && useFor === 'tooltip' && showCorrelation">
          <el-table
            class="config-panel-table mapping-table"
            :data="form.correlatedData"
            :row-style="{ height: '25px' }"
            :header-row-style="{ height: '25px' }"
            :header-cell-style="{ lineHeight: '15px' }"
          >
            <el-table-column
              :render-header="renderTableHeader"
              prop="priKey"
              :label="$demoi18n('panel.tooltipData.compField')"
              width="180"
            >
              <template #default="scope">
                <span class="mapping-scope">
                  *
                </span>
                <VsFormItem :prop="`correlatedData[${scope.$index}].priKey`" :rules="generateRules()">
                  <el-select
                    v-model="scope.row.priKey"
                    clearable
                    filterable
                    allow-create
                    default-first-option
                    size="default"
                    :class="'panel-data-select-' + xvueTheme"
                    :popper-class="'select-poper-' + xvueTheme"
                  >
                    <el-option v-for="(n, i) in mainVars" :key="i" :label="`${i}`" :value="i"></el-option>
                  </el-select>
                </VsFormItem>
              </template>
            </el-table-column>
            <el-table-column
              :render-header="renderTableHeader"
              prop="priMapKey"
              :label="$demoi18n('panel.tooltipData.apiCorrelateField')"
              width="180"
            >
              <template #default="scope">
                <span class="mapping-scope">
                  *
                </span>
                <VsFormItem :prop="`correlatedData[${scope.$index}].priKey`" :rules="generateRules()">
                  <el-select
                    v-model="scope.row.priMapKey"
                    clearable
                    size="default"
                    :class="'panel-data-select-' + xvueTheme"
                    :popper-class="'select-poper-' + xvueTheme"
                  >
                    <el-option
                      v-for="item in mappingOptions"
                      :key="item.id"
                      :label="`${item.option_label}`"
                      :value="item.option_value"
                    ></el-option>
                  </el-select>
                </VsFormItem>
              </template>
            </el-table-column>
            <el-table-column width="50">
              <template #default="scope">
                <el-button
                  icon="Delete"
                  :link="true"
                  type="primary"
                  :disabled="form.correlatedData.length === 1"
                  @click.stop="deleteCurRow(scope)"
                ></el-button>
              </template>
            </el-table-column>
          </el-table>
          <el-button class="btn-sure" size="default" icon="CirclePlus" @click.stop="addNewRow()">
            {{ $demoi18n('btn.add') }}
          </el-button>
        </div>
      </div>
    </el-form>

    <!-- 保存，取消-->
    <div class="bottom-btns">
      <el-button class="button-cancel" size="default" @click="cancel">
        {{ $demoi18n('btn.cancel') }}
      </el-button>
      <el-button class="btn-sure" type="primary" size="default" @click="save">
        {{ $demoi18n('btn.save') }}
      </el-button>
    </div>
  </div>
</template>
<script lang="jsx">
import dataModel from '@/models/panel-config-data.js';
import { generateRules } from '@/utils/rules';
import PanelLabelOverflowTooltip from '@/components/common/overflow-tooltip/overflow-tooltip.vue';
import AutoRefreshSetting from '@/components/common/auto-refresh/auto-refresh-setting.vue';
import ValueInputer from '@/components/common/value-inputer/value-inputer.vue';
import { getLowCodeExpVal } from '@/components/common/low-code/low-code-util.js';
import formMixin from '@/mixin/form-mixin.js';
import FabricApiList from '@/components/panel-data/fabric-api-list';
import XMinerApiList from '@/components/panel-data/xMiner-api-list';

const defaultForm = {
  useParentData: false,
  dataSourceType: '',
  dataSource: '',
  apiCode: '',
  dataVal: '',
  correlation: 'correlate', // 数据关联情况
  correlatedData: [
    {
      priKey: '',
      priMapKey: '',
    },
  ], // 关联字段数据
  priKey: '', // 主表主键
  priMapKey: '', // 映射主键
  apiFields: [],
  conf: {},
};
const autoRefresh = {
  switchEnable: false,
  actTypes: ['pull'],
  actType: 'pull',
  interval: 300,
};
export default {
  name: 'TooltipData',
  components: { PanelLabelOverflowTooltip, AutoRefreshSetting, XMinerApiList, FabricApiList },
  mixins: [formMixin],
  inject: {
    getParentRefVm: {
      default: () => {},
    },
    isChildComponent: {
      default: false,
    },
  },
  props: {
    mainVars: {

      // 主表变量
      type: Object,
      default: () => ({}),
    },
    apiConf: {
      type: Object,
      default: () => {
        const conf = this.getDefaultForm();
        if (!this.showCorrelation) {
          conf[correlation] = 'discorrelate';
        }

        // 悬浮文本支持实时数据pull
        if (this.useFor === 'hover-text') {
          conf.autoRefresh = JSON.parse(JSON.stringify(autoRefresh));
        }
        return conf;
      },
    },
    useFor: String, // tooltip | hover-text, 用于区分用途

    // 是否显示关联选择
    showCorrelation: {
      type: Boolean,
      default: true,
    },

    // 额外配置，用于悬浮文本
    extraConfig: {
      type: Object,
      default: () => ({}),
    },

    widgetInstanceId: String,
  },
  emits: ['save', 'cancel'],
  data() {
    // 悬浮文本支持实时数据pull & api-fabric
    const _form = this.getDefaultForm();
    const dataSourceTypeOptions = [
      { label: 'xMiner', value: 'xMiner' },
      {
        label: this.$demoi18n('panelData.xMinerPublicDatabase'),
        value: 'xMinerPublicDatabase',
      },
      { label: this.$demoi18n('panel_config.xvuePageApi'), value: 'xVueApi' },
      { label: this.$demoi18n('panelData.dacDataSource'), value: 'Dac' },
    ];
    if (this.useFor === 'hover-text') {
      _form.autoRefresh = JSON.parse(JSON.stringify(autoRefresh));
      dataSourceTypeOptions.push({
        label: this.$demoi18n('panelData.thirdPartyApi'),
        value: 'fabric',
      });
    }
    return {
      xvueTheme: window._adoPremise.uc.theme,
      isLoading: false,
      dataSourceTypeOptions,
      dataSourceList: [],
      apiList: [],
      mappingOptions: [],
      form: _form,
      rules: {
        dataSourceType: generateRules({
          label: this.$demoi18n('panel.label.dataSourceType'),
        }),
        dataSource: generateRules({
          label: this.$demoi18n('panel.label.selectDataSource'),
        }),
        apiCode: generateRules({
          label: this.$demoi18n('panel.label.selectApi'),
        }),
        dataVal: generateRules({
          label: this.$demoi18n('panel.tab.data'),
        }),
      },
    };
  },
  computed: {
    isXMiner() {
      return ['xMiner', 'xMinerRedisRealTime', 'kafka', 'Dac'].includes(this.form.dataSourceType);
    },
    isDebugger() {
      if (window.isLocalEnv && window.location.href.includes('debugger')) {
        return true;
      }
      return false;
    },
    fItemConf() {
      const fItemConf = {
        dataVal: {
          label: this.$demoi18n('panel.tab.data'),
          type: 'text',
          required: true,
          specilChar: true,
        },
      };
      return fItemConf;
    },
  },
  watch: {
    dataSourceList() {
      if (this.isDebugger) {
        this.form.dataSource = this.apiConf.dataSource || 'sa_service';
      }
    },
    apiList(list) {
      if (this.isDebugger) {
        if (list && list.length) {
          this.form.apiCode = this.apiConf.apiCode || 'test3';
        }
      }
    },
    mappingOptions(val) {
      this.form.apiFields = JSON.parse(JSON.stringify(val));
    },
    apiConf: {
      handler: function(conf, oldConf) {
        let _conf = conf;
        if (this.$refs.form) {
          this.$refs.form.resetFields();
        }
        _conf = {
          ...this.getDefaultForm(),
          ..._conf,
        };

        // 悬浮文本支持实时数据pull
        if (this.useFor === 'hover-text') {
          _conf.autoRefresh = conf.autoRefresh || JSON.parse(JSON.stringify(autoRefresh));
        }
        this.conf = JSON.parse(JSON.stringify(_conf));
        this.form['correlatedData'] = [
          {
            priKey: '',
            priMapKey: '',
          },
        ];
        for (const i in this.form) {
          if (i === 'apiCode' || i === 'correlatedData') {
            continue;
          }

          this.form[i] = _conf[i];
        }
      },
      deep: true,
      immediate: true,
    },
    'form.useParentData'(val, oldVal) {
      this.useParentDataChange();
    },
    'form.dataVal': {
      handler(val) {
        if (val) {
          this.mappingOptions = this.getMappingOptionsByExp(val);
        }
      },
      immediate: true,
    },
  },
  created() {
    if (!this.form.dataVal) { // 低代码数据值
      this.form.dataVal = '';
    }
  },
  mounted() {
    if (!this.form.correlatedData.length) {
      this.addNewRow();
    }
    if (this.isDebugger) {
      this.form.dataSourceType = 'xMiner';
      this.form.correlation = this.apiConf.correlation || 'correlate';
    }
    if (!this.showCorrelation) {
      this.form.correlation = 'discorrelate';
    }
  },
  methods: {
    generateRules,
    onDatasourceTypeChange(value) {
      this.form.dataSource = '';
      this.dataSourceList = [];
      this.form.apiCode = '';
      this.form.dataVal = '';
      this.apiList = [];
      this.mappingOptions = [];
      this.form.priMapKey = '';
      this.form.correlatedData = [
        {
          priKey: '',
          priMapKey: '',
        },
      ];
      if (!value || value === 'xVueApi') {
        return;
      }
      this.getDataSourceList();
    },
    onDatasourceChange(value) {
      this.form.apiCode = '';
      this.apiList = [];
      this.mappingOptions = [];
      this.form.priMapKey = '';
      this.form.correlatedData = [
        {
          priKey: '',
          priMapKey: '',
        },
      ];
      if (!value) {
        return;
      }
      this.getApiList();
    },
    onApiCodeChange(value) {
      this.form.priMapKey = '';
      this.mappingOptions = [];
      this.form.correlatedData = [
        {
          priKey: '',
          priMapKey: '',
        },
      ];
      if (!value) {
        return;
      }
      this.getMappingOptions();
    },

    getMappingOptionsByExp(expression) {
      let data = getLowCodeExpVal({ expression });
      if (typeof data === 'string') {
        data = [];
      }
      if (data.length === 0) {
        return [];
      }
      const options = Object.entries(data[0] || {}).map(([key]) => ({
        'option_label': key,
        'option_value': key,
      }));
      return options;
    },

    // 打开弹窗时操作
    openDialog() {
      if (this.conf.dataSourceType) {
        this.form.dataSourceType = this.conf.dataSourceType;
      }
      if (this.conf.dataSource) {
        this.form.dataSource = this.conf.dataSource;
      }
      if (this.conf.apiCode) {
        this.form.apiCode = this.conf.apiCode;
      }
      if (this.conf.correlatedData) {
        this.form.correlatedData = this.conf.correlatedData;
      }
      this.useParentDataChange();
    },
    delTooltipReqParamsInXvue(apiCode) {
      const arr = app.config.globalProperties.$xvuePageComponentApiMap || [];
      const curInstanceIndex = arr.findIndex(item => item.instance === this.widgetInstanceId);
      if (curInstanceIndex === -1) {
        return;
      }
      const apis = arr[curInstanceIndex] && arr[curInstanceIndex]['apis'];
      const toDelApiIndex = apis ? apis.findIndex(item => item.apiCode === apiCode) : -1;
      if (toDelApiIndex > -1) {
        app.config.globalProperties.$xvuePageComponentApiMap[curInstanceIndex]['apis'].splice(toDelApiIndex, 1);
      }
    },
    getPanelLabelOverflowTooltip() {
      return {
        parentComp: this,
      };
    },
    getDataSourceList() {
      this.dataSourceList = [];
      const method = `getDataSourceList${this.form.dataSourceType}`;
      if (!this.form.dataSourceType) {
        return false;
      }
      this.isLoading = true;
      return dataModel[method]()
        .then(list => {
          this.dataSourceList = list;
        })
        .finally(() => {
          this.isLoading = false;
        });
    },
    getApiList() {
      this.apiCode = '';
      if (!this.form.dataSourceType) {
        return false;
      }
      this.isLoading = true;
      const apiMethod = `getApiList${this.form.dataSourceType}`;
      return dataModel[apiMethod](this.form.dataSource)
        .then(list => {
          this.apiList = list;
        })
        .finally(() => {
          this.isLoading = false;
        });
    },
    getMappingOptions() {
      this.mappingOptions = [];
      const item = this.apiList.find(n => n.code === this.form.apiCode);
      if (!item) {
        return false;
      }
      if (!this.form.dataSourceType) {
        return false;
      }
      this.isLoading = true;

      let { id } = item;
      if (this.form.dataSourceType === 'fabric') {
        id = item.code;
      }
      const method = `getMappingOptions${this.form.dataSourceType}`;
      return dataModel[method](id)
        .then(({ list }) => {
          const _list = list.map(n => {
            n['option_name'] = window._adoPremise.language === 'zh-CN' ? n.name || n.nameEn : n.nameEn;
            n['option_label'] = n.option_name;
            return {
              'option_label': n.option_label,
              'option_value': n.option_value,
              'option_name': n.option_name,
            };
          });

          this.mappingOptions = _list;
        })
        .finally(() => {
          this.isLoading = false;
        });
    },
    renderHeader(h, params) {
      const a = [
        h(
          'el-button',
          {
            props: {
              size: 'mini',
              type: 'primary',
            },
            on: {
              click: () => {
                this.addField();
              },
            },
          },
          '+',
        ),
      ];
      return h('div', a);
    },
    async save() {
      if (!this.validChildForms()) {
        return false;
      }

      this.$refs.form.validate(valid => {
        if (valid) {
          const flag = this.checkCorrelatedData();
          if (flag) {
            this.getLabels();
            this.$emit('save', this.form);
            return true;
          } else {
            this.$message({
              message: this.$demoi18n('message.dataAssociationFieldEmpty'),
              type: 'warning',
            });
            return false;
          }
        } else {
          return false;
        }
      });
      return true;
    },
    cancel() {
      this.$emit('cancel', this.form);
    },

    // 关联数据增加新行
    addNewRow() {
      this.form.correlatedData.push({
        priKey: '',
        priMapKey: '',
      });
    },

    // 关联数据删除选中行
    deleteCurRow(scope) {
      this.form.correlatedData.splice(scope.$index, 1);
    },
    checkCorrelatedData() {
      let flag = true;
      if (this.useFor === 'hover-text' || !this.showCorrelation) {
        this.form.correlation = 'discorrelate';
      }
      if (!this.form.correlatedData.length) {
        flag = false;
      }
      this.form.correlatedData.forEach(item => {
        if (!item.priKey || !item.priMapKey) {
          flag = false;
        }
      });
      if (this.form.correlation === 'discorrelate') {
        flag = true;
      }
      return flag;
    },

    // 获取对应key 的label值,用于tooltip弹窗展示
    getLabels() {
      const dataSourceType = this.dataSourceTypeOptions.find(o => String(o.value) === String(this.form.dataSourceType));
      this.form['dataSourceType_label'] = dataSourceType ? dataSourceType.label : '';

      const dataSource = this.dataSourceList.find(o => String(o.option_value) === String(this.form.dataSource));
      this.form['dataSource_label'] = dataSource ? dataSource.option_label : '';

      const api = this.apiList.find(o => String(o.option_value) === String(this.form.apiCode));
      this.form['apiCode_label'] = api ? api.option_label : '';

      // 使用父组件数据
      if (this.form.useParentData) {
        this.form['dataSourceType_label'] = this.$demoi18n('common.usingParentData');
        this.form['dataSource_label'] = '';
        this.form['apiCode_label'] = '';
      }

      // 关联数据字段
      this.form.correlatedData.forEach(item => {
        if (!item.priKey || !item.priMapKey) {
          return;
        }
        item['priKey_label'] = this.mainVars[item.priKey];
        const priMapKeyObj = this.mappingOptions.find(o => String(o.option_value) === String(item.priMapKey));
        item['priMapKey_label'] = priMapKeyObj ? priMapKeyObj.option_label : '';
      });
    },
    getDefaultForm() {
      const form = JSON.parse(JSON.stringify(defaultForm));
      if (this.isChildComponent) {
        form.useParentData = true;
      }
      return form;
    },
    async useParentDataChange() {
      if (this.form.useParentData) {
        const vm = this.getParentRefVm('panel_data');
        const parentForm = this.getParentRefVm('panel_data').form;
        this.form.apiFields = parentForm.tableData.map(n => ({
          'option_label': n.field,
          'option_value': n.field,
          'option_name': n.field,
        }));
      } else {
        if (this.form.dataSourceType !== 'xVueApi') {
          await this.getDataSourceList();
          await this.getApiList();
          await this.getMappingOptions();
        }
      }
    },
    renderTableHeader({ column }) {
      return (
        <el-tooltip placement="top" content={column.label} effect={this.xvueTheme}>
          <span>{column.label}</span>
        </el-tooltip>
      );
    },
  },
};
</script>
<style lang="less" scoped>
.tooltip-data {
  width: 400px;
  :deep(.el-form-item) {
    margin-bottom: 0px;
    .el-form-item__label {
      text-overflow: ellipsis;
      white-space: nowrap;
      overflow: hidden;
    }

    .el-form-item__error {
      top: 100%;
      padding-top: 0;
    }
  }
  .is-error {
    margin-bottom: 15px;
  }
  .mapping-scope {
    color: #f56c6c;
    position: absolute;
    left: 0px;
    top: 15%;
  }

  :deep(.config-panel-table) {
    .el-form-item__content {
      margin-left: 0 !important;
    }
    td {
      padding: 2px;
    }
    .cell {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }
  .bottom-btns {
    display: flex;
    justify-content: center;
    margin-top: 20px;
  }
}
</style>

<style lang="less">
.panel-data-select-dark {
  :deep(.el-input) {
    .el-input__inner {
      border-color: #588ba8;
      color: #fff;
      background-color: #091a2d;
    }
    .el-input__icon {
      color: #588ba8;
    }
  }
}

.select-poper-dark {
  background-color: #091a2d;
  border-color: #588ba8;

  :deep(.el-scrollbar) {
    .el-select-dropdown__list {
      .el-select-dropdown__item {
        padding: 0 12px;
        height: 24px;
        line-height: 24px;
        font-size: 12px;
        color: #fff;
        background-color: #091a2d;

        .select-icon {
          padding: 0;
        }

        .select-option-slot-text {
          display: inline-block;
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
          color: #178ddf;
        }
        .select-option-slot-icon {
          display: inline-block;
          vertical-align: top;
        }
      }
      .hover {
        background-color: #102e4f;
      }
    }
  }
  :deep(.popper__arrow) {
    border-bottom-color: #588ba8;
    &::after {
      border-bottom-color: #091a2d !important;
    }
  }
}

.select-poper-light {
  :deep(.el-scrollbar) {
    .el-select-dropdown__list {
      .el-select-dropdown__item {
        padding: 0 12px;
        height: 24px;
        line-height: 24px;
        font-size: 12px;
        .select-icon {
          padding: 0;
        }

        .select-option-slot-text {
          display: inline-block;

          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
        }
        .select-option-slot-icon {
          display: inline-block;
          vertical-align: top;
        }
      }
    }
  }
}

.visualComponents_theme_dark {
  .tooltip-data {
    .el-table {
      th,
      td {
        background-color: #122b40;
        border-color: transparent;
      }
    }
    .el-table--border::after,
    .el-table--group::after,
    .el-table::before {
      background-color: transparent;
    }
    .el-table--border,
    .el-table--group {
      border-color: #1a3f60 !important;
    }
    .el-table--enable-row-hover {
      .el-table__body {
        tr:hover > td {
          background-color: #255074;
        }
      }
    }
  }
}
</style>
